package io.github.hadyang.leetcode.random;

import io.github.hadyang.leetcode.ListNode;
import org.junit.Test;

/**
 * 给定一个链表，返回链表开始入环的第一个节点。 如果链表无环，则返回 null。
 *
 * <p>为了表示给定链表中的环，我们使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。 如果 pos 是 -1，则在该链表中没有环。
 *
 * <p>说明：不允许修改给定的链表。
 *
 * <p>示例 1：
 *
 * <p>输入：head = [3,2,0,-4], pos = 1 输出：tail connects to node index 1 解释：链表中有一个环，其尾部连接到第二个节点。
 *
 * <p>示例 3：
 *
 * <p>输入：head = [1], pos = -1 输出：no cycle 解释：链表中没有环。
 *
 * <p>来源：力扣（LeetCode） 链接：https://leetcode-cn.com/problems/linked-list-cycle-ii
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class Q142 {
  public ListNode detectCycle(ListNode head) {
    if (head == null || head.next == null) return null;

    ListNode slow = head;
    ListNode fast = head;
    while (fast != null) {
      slow = slow.next;
      if (fast.next == null) return null;
      fast = fast.next.next;

      if (slow == fast) {
        break;
      }
    }

    if (fast == null) return null;

    // 重置slow
    slow = head;
    while (fast != null) {
      if (slow == fast) return slow;

      //两个指针均 1 step
      slow = slow.next;
      fast = fast.next;
    }

    return null;
  }

  @Test
  public void test1() {
    ListNode node1 = new ListNode(3);
    ListNode node2 = new ListNode(2);
    ListNode node3 = new ListNode(0);
    ListNode node4 = new ListNode(4);

    node1.next = node2;
    node2.next = node3;
    node3.next = node4;
    node4.next = node2;
    System.out.println(detectCycle(node1));
  }

  @Test
  public void test2() {
    ListNode node1 = new ListNode(1);
    ListNode node2 = new ListNode(2);

    node1.next = node2;
    node2.next = node1;
    System.out.println(detectCycle(node1));
  }
}
